package astudy.datasource.dbf;

import java.text.*;
import java.util.Date;

public class Field {

	private String name;
	private char type;
	private int length;
	private int decimalCount;

	public Field(String s, char c, int i, int j) throws DBFException {

		if (s.length() > 10) {
			throw new DBFException("The field name '" + s +  "' is more than 10 characters long!");
		}
		if (c != 'C' && c != 'N' && c != 'L' && c != 'D' && c != 'F') {
			throw new DBFException("The field type '" + c + "' is not a valid. Only 'C', 'N', 'L', 'D', 'F' are allowed.");
		}
		if (i < 1) {
			throw new DBFException("The field length '" + i + "' should be a positive integer.");
		}
		if (c == 'C' && i >= 254) {
			throw new DBFException("The field length '" + i + "' should be less than 254 characters for character fields.");
		}
		if (c == 'N' && i >= 21) {
			throw new DBFException("The field length '" + i + "' should be less than 21 digits for numeric fields.");
		}
		if (c == 'L' && i != 1) {
			throw new DBFException("The field length '" + i + "' should be 1 characater for logical fields.");
		}
		if (c == 'D' && i != 8) {
			throw new DBFException("The field length '" + i + "' should be 8 characaters for date fields.");
		}
		if (c == 'F' && i >= 21) {
			throw new DBFException("The field length '" + i + "' should be less than 21 digits for floating point fields.");
		}
		if (j < 0) {
			throw new DBFException("The field decimal count '" + j + " ' should not be a negative integer.");
		}
		if ((c == 'C' || c == 'L' || c == 'D') && j != 0) {
			throw new DBFException("The field decimal count '" + j + "' should be 0 for character, logical, and date fields.");
		}
		if (j > i - 1) {
			throw new DBFException("The field decimal count '" + j + " ' should be less than the length - 1.");
		} else {
			name = s;
			type = c;
			length = i;
			decimalCount = j;
			return;
		}
	}

	public String getName() {
		return name;
	}

	public char getType() {
		return type;
	}

	public int getLength() {
		return length;
	}

	public int getDecimalCount() {
		return decimalCount;
	}

	public String format(Object obj) throws DBFException {

		if (type == 'N' || type == 'F') {
			if (obj == null) {
				obj = new Double(0.0D);
			}

			if (obj instanceof Number) {
				Number number = (Number) obj;
				StringBuffer stringbuffer = new StringBuffer(getLength());

//				for(int i = 0; i < getLength(); i++) {
//					stringbuffer.append("#"); if(getDecimalCount() > 0)
//				}
//				stringbuffer.setCharAt(getLength() - getDecimalCount() - 1, '.');

				//get decimalFormat
				for (int i = 0; i < getLength() - getDecimalCount() - 2; i++) {
					stringbuffer.append("#");
				}
				if (getDecimalCount() > 0) {
					stringbuffer.append("0.");
				} else {
					stringbuffer.append("#0");
				}
				for (int i = 0; i < getDecimalCount(); i++) {
					stringbuffer.append("0");
				}
				DecimalFormat decimalformat = new DecimalFormat(stringbuffer.toString());

				String s1 = decimalformat.format(number);
				int k = getLength() - s1.length();
				if (k < 0) {
					throw new DBFException("Value " + number + " cannot fit in pattern: '" + stringbuffer + "'.");
				}
				StringBuffer stringbuffer2 = new StringBuffer(k);
				for (int l = 0; l < k; l++) {
					stringbuffer2.append(" ");
				}
				return stringbuffer2 + s1;
			} else {
				throw new DBFException("Expected a Number, got " + obj.getClass() + ".");
			}
		} else if (type == 'C') {
			if (obj == null) {
				obj = "";
			}
			if (obj instanceof String) {
				String s = (String) obj;
				if (s.length() > getLength()) {
					throw new DBFException("'" + obj + "' is longer than " + getLength() + " characters.");
				}
				StringBuffer stringbuffer1 = new StringBuffer(getLength() - s.length());
				for (int j = 0; j < getLength() - s.length(); j++) {
					stringbuffer1.append(' ');
				}
				return s + stringbuffer1;
			} else {
				throw new DBFException("Expected a String, got " + obj.getClass() + ".");
			}
		} else if (type == 'L') {
			if (obj == null) {
				obj = new Boolean(false);
			}
			if (obj instanceof Boolean) {
				Boolean boolean1 = (Boolean) obj;
				return boolean1.booleanValue() ? "Y" : "N";
			} else {
				throw new DBFException("Expected a Boolean, got " + obj.getClass() + ".");
			}
		} else if (type == 'D') {
			if (obj == null) {
				return "        "; // 8 blank
			} else if (obj instanceof Date) {
				Date date = (Date) obj;
				SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyyMMdd");
				return simpledateformat.format(date);
			} else {
				throw new DBFException("Expected a Date, got " + obj.getClass() + ".");
			}
		} else {
			throw new DBFException("Unrecognized JDBFField type: " + type);
		}
	}

	public Object parse(String s) throws DBFException {

		if (s == null) {
			return null;
		} else if (type == 'C') {
			return s;
		} else {
			s = s.trim();
		}
		if (type == 'N' || type == 'F') {
			try {
				s = s.replaceAll(",", ""); // remove ","
				if (s.equals("")) {
					return null;
				}

				if (getDecimalCount() == 0) {
					return new Long(s);
				} else {
					return new Double(s);
				}
			} catch (NumberFormatException e) {
				throw new DBFException(e);
			}
		} else if (type == 'L') {
			if (s.equals("")) {
				return null;
			}
			if (s.equals("Y") || s.equals("y") || s.equals("T") || s.equals("t")) {
				return new Boolean(true);
			}
			if (s.equals("N") || s.equals("n") || s.equals("F") || s.equals("f")) {
				return new Boolean(false);
			} else {
				throw new DBFException("Unrecognized value for logical field: " + s);
			}
		} else if (type == 'D') {
			SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyyMMdd");

			// 2005-06-13 twang: �����һ�ַָ�� : "."
			String[] sep = { "_", "-", "/", "\\", "." };
			String[] rep = { "_", "-", "/", "\\\\", "\\." };
			String separator = null;
			for (int i = 0; i < sep.length; i++) {
				if (s.indexOf(sep[i]) != -1) {
					separator = rep[i];
					break;
				}
			}

			if (separator != null) {
				String dateStringArray[] = null;
				dateStringArray = s.split(separator);
				s = "";
				for (int i = 0; dateStringArray != null
						&& i < dateStringArray.length; i++) {
					if (dateStringArray[i].length() == 1) {
						s += ("0" + dateStringArray[i]);
					} else {
						s += dateStringArray[i];
					}
				}
			}

			try {
				if (s.length() != 8) {
					throw new DBFException("Unrecognized value for Date(yyyyMMdd): date = " + s);
				} else {
					return simpledateformat.parse(s);
				}
			} catch (ParseException e) {
				throw new DBFException(e);
			}
		} else {
			throw new DBFException("Unrecognized JDBFField type: " + type + ", value = " + s);
		}
	}

	public String toString() {
		return name + "(" + type + ":" + length + "." + decimalCount + ")";
	}

}
